home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / lynx-2.4 / WWW / Library / Implementation / HTAAProt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-28  |  15.7 KB  |  607 lines

  1.  
  2. /* MODULE                            HTAAProt.c
  3. **        PROTECTION FILE PARSING MODULE
  4. **
  5. ** AUTHORS:
  6. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  7. **    MD    Mark Donszelmann    duns@vxdeop.cern.ch
  8. **
  9. ** HISTORY:
  10. **    20 Oct 93  AL    Now finds uid/gid for nobody/nogroup by name
  11. **            (doesn't use default 65534 right away).
  12. **            Also understands negative uids/gids.
  13. **    14 Nov 93  MD    Added VMS compatibility
  14. **
  15. ** BUGS:
  16. **
  17. **
  18. */
  19.  
  20. #include "HTUtils.h"
  21.  
  22. #include <string.h>
  23. #ifndef VMS
  24. #include <pwd.h>    /* Unix password file routine: getpwnam()    */
  25. #include <grp.h>    /* Unix group file routine: getgrnam()        */
  26. #endif /* not VMS */
  27.  
  28. #include "HTAAUtil.h"
  29. #include "HTAAFile.h"
  30. #include "HTLex.h"    /* Lexical analysor    */
  31. #include "HTAssoc.h"    /* Association list    */
  32. #include "HTAAProt.h"    /* Implemented here    */
  33.  
  34. #include "LYLeaks.h"
  35.  
  36. /*
  37. ** Protection setup caching
  38. */
  39. typedef struct {
  40.     char *    prot_filename;
  41.     HTAAProt *    prot;
  42. } HTAAProtCache;
  43.  
  44. PRIVATE HTList *  prot_cache    = NULL;    /* Protection setup cache.    */
  45. PRIVATE HTAAProt *default_prot    = NULL;    /* Default protection.        */
  46. PRIVATE HTAAProt *current_prot    = NULL;    /* Current protection mode    */
  47.                                         /* which is set up by callbacks    */
  48.                                         /* from the rule system when    */
  49.                                         /* a "protect" rule is matched.    */
  50.  
  51.  
  52.  
  53. /* PRIVATE                            isNumber()
  54. **        DOES A CHARACTER STRING REPRESENT A NUMBER
  55. */
  56. PRIVATE BOOL isNumber ARGS1(CONST char *, s)
  57. {
  58.     CONST char *cur = s;
  59.  
  60.     if (!s || !*s) return NO;
  61.  
  62.     if (*cur == '-')
  63.     cur++;        /* Allow initial minus sign in a number */
  64.  
  65.     while (*cur) {
  66.     if (*cur < '0' || *cur > '9')
  67.         return NO;
  68.     cur++;
  69.     }
  70.     return YES;
  71. }
  72.  
  73.  
  74. #ifdef VMS
  75.  
  76. /* PUBLIC                            HTAA_getUidName()
  77. **        GET THE USER ID NAME (VMS ONLY)
  78. ** ON ENTRY:
  79. **    No arguments.
  80. **
  81. ** ON EXIT:
  82. **    returns    the user name 
  83. **        Default is "" (nobody).
  84. */
  85. PUBLIC char * HTAA_getUidName NOARGS
  86. {
  87.     if (current_prot && current_prot->uid_name 
  88.                   && (0 != strcmp(current_prot->uid_name,"nobody")) )
  89.        return(current_prot->uid_name);
  90.     else
  91.        return("");
  92. }
  93.  
  94. /* PUBLIC                            HTAA_getFileName
  95. **        GET THE FILENAME (VMS ONLY)
  96. ** ON ENTRY:
  97. **    No arguments.
  98. **
  99. ** ON EXIT:
  100. **    returns    the filename
  101. */
  102. PUBLIC char * HTAA_getFileName NOARGS
  103. {
  104.     if (current_prot && current_prot->filename)
  105.        return(current_prot->filename);
  106.     else
  107.        return("");
  108. }
  109.  
  110. #else /* not VMS */
  111.  
  112. /* PUBLIC                            HTAA_getUid()
  113. **        GET THE USER ID TO CHANGE THE PROCESS UID TO
  114. ** ON ENTRY:
  115. **    No arguments.
  116. **
  117. ** ON EXIT:
  118. **    returns    the uid number to give to setuid() system call.
  119. **        Default is 65534 (nobody).
  120. */
  121. PUBLIC int HTAA_getUid NOARGS
  122. {
  123.     struct passwd *pw = NULL;
  124.  
  125.     if (current_prot  &&  current_prot->uid_name) {
  126.     if (isNumber(current_prot->uid_name)) {
  127.         if (NULL != (pw = getpwuid(atoi(current_prot->uid_name)))) {
  128.         if (TRACE) fprintf(stderr, 
  129.                    "%s(%s) returned (%s:%s:%d:%d:...)\n",
  130.                    "HTAA_getUid: getpwuid",
  131.                    current_prot->uid_name,
  132.                    pw->pw_name, pw->pw_passwd,
  133.                    pw->pw_uid, pw->pw_gid);
  134.         return pw->pw_uid;    
  135.         }
  136.     }
  137.     else {    /* User name (not a number) */
  138.         if (NULL != (pw = getpwnam(current_prot->uid_name))) {
  139.         if (TRACE) fprintf(stderr, "%s(\"%s\") %s (%s:%s:%d:%d:...)\n",
  140.                    "HTAA_getUid: getpwnam",
  141.                    current_prot->uid_name, "returned",
  142.                    pw->pw_name, pw->pw_passwd,
  143.                    pw->pw_uid, pw->pw_gid);
  144.         return pw->pw_uid;
  145.         }
  146.     }
  147.     }
  148.     /*
  149.     ** Ok, then let's get uid for nobody.
  150.     */
  151.     if (NULL != (pw = getpwnam("nobody"))) {
  152.     if (TRACE) fprintf(stderr, "HTAA_getUid: Uid for `nobody' is %d\n",
  153.                pw->pw_uid);
  154.     return pw->pw_uid;
  155.     }
  156.     /*
  157.     ** Ok, then use default.
  158.     */
  159.     return 65534;    /* nobody */
  160. }
  161.  
  162.  
  163.  
  164. /* PUBLIC                            HTAA_getGid()
  165. **        GET THE GROUP ID TO CHANGE THE PROCESS GID TO
  166. ** ON ENTRY:
  167. **    No arguments.
  168. **
  169. ** ON EXIT:
  170. **    returns    the uid number to give to setgid() system call.
  171. **        Default is 65534 (nogroup).
  172. */
  173. PUBLIC int HTAA_getGid NOARGS
  174. {    
  175.     struct group *gr = NULL;
  176.     
  177.     if (current_prot  &&  current_prot->gid_name) {
  178.     if (isNumber(current_prot->gid_name)) {
  179.         if (NULL != (gr = getgrgid(atoi(current_prot->gid_name)))) {
  180.         if (TRACE) fprintf(stderr,
  181.                    "%s(%s) returned (%s:%s:%d:...)\n",
  182.                    "HTAA_getGid: getgrgid",
  183.                    current_prot->gid_name,
  184.                    gr->gr_name, gr->gr_passwd, gr->gr_gid);
  185.         return gr->gr_gid;
  186.         }
  187.     }
  188.     else {    /* Group name (not number) */
  189.         if (NULL != (gr = getgrnam(current_prot->gid_name))) {
  190.         if (TRACE) fprintf(stderr, 
  191.                    "%s(\"%s\") returned (%s:%s:%d:...)\n",
  192.                    "HTAA_getGid: getgrnam",
  193.                    current_prot->gid_name,
  194.                    gr->gr_name, gr->gr_passwd, gr->gr_gid);
  195.         return gr->gr_gid;
  196.         }
  197.     }
  198.     }
  199.     /*
  200.     ** Ok, then let's get gid for nogroup.
  201.     */
  202.     if (NULL != (gr = getgrnam("nogroup"))) {
  203.     if (TRACE) fprintf(stderr, "HTAA_getGid: Gid for `nogroup' is %d\n",
  204.                gr->gr_gid);
  205.     return gr->gr_gid;
  206.     }
  207.     /*
  208.     ** Ok, then use default.
  209.     */
  210.     return 65534;    /* nogroup */
  211. }
  212.  
  213. #endif /* not VMS */
  214.  
  215.  
  216.  
  217.  
  218. /* PRIVATE                            HTAA_setIds()
  219. **        SET UID AND GID (AS NAMES OR NUMBERS)
  220. **        TO HTAAProt STRUCTURE
  221. ** ON ENTRY:
  222. **    prot        destination.
  223. **    ids        is a string like "james.www" or "1422.69" etc.
  224. **            giving uid and gid.
  225. **
  226. ** ON EXIT:
  227. **    returns        nothing.
  228. */
  229. PRIVATE void HTAA_setIds ARGS2(HTAAProt *,    prot,
  230.                    CONST char *,    ids)
  231. {
  232.     if (ids) {
  233.     char *local_copy = NULL;
  234.     char *point;
  235.  
  236.     StrAllocCopy(local_copy, ids);
  237.     point = strchr(local_copy, '.');
  238.     if (point) {
  239.         *(point++) = (char)0;
  240.         StrAllocCopy(prot->gid_name, point);
  241.     }
  242.     else {
  243.         StrAllocCopy(prot->gid_name, "nogroup");
  244.     }
  245.     StrAllocCopy(prot->uid_name, local_copy);
  246.     FREE(local_copy);
  247.     }
  248.     else {
  249.     StrAllocCopy(prot->uid_name, "nobody");
  250.     StrAllocCopy(prot->gid_name, "nogroup");
  251.     }
  252. }
  253.  
  254.  
  255.  
  256. /* PRIVATE                        HTAA_parseProtFile()
  257. **        PARSE A PROTECTION SETUP FILE AND
  258. **        PUT THE RESULT IN A HTAAProt STRUCTURE
  259. ** ON ENTRY:
  260. **    prot        destination structure.
  261. **    fp        open protection file.
  262. **
  263. ** ON EXIT:
  264. **    returns        nothing.
  265. */
  266. PRIVATE void HTAA_parseProtFile ARGS2(HTAAProt *, prot,
  267.                       FILE *,      fp)
  268. {
  269.     if (prot && fp) {
  270.     LexItem lex_item;
  271.     char *fieldname = NULL;
  272.  
  273.     while (LEX_EOF != (lex_item = lex(fp))) {
  274.  
  275.         while (lex_item == LEX_REC_SEP)    /* Ignore empty lines */
  276.         lex_item = lex(fp);
  277.  
  278.         if (lex_item == LEX_EOF)        /* End of file */
  279.         break;
  280.  
  281.         if (lex_item == LEX_ALPH_STR) {    /* Valid setup record */
  282.         
  283.         StrAllocCopy(fieldname, lex_buffer);
  284.         
  285.         if (LEX_FIELD_SEP != (lex_item = lex(fp)))
  286.             unlex(lex_item);    /* If someone wants to use colon */
  287.                                 /* after field name it's ok, but */
  288.                                 /* not required. Here we read it.*/
  289.  
  290.         if (0==strncasecomp(fieldname, "Auth", 4)) {
  291.             lex_item = lex(fp);
  292.             while (lex_item == LEX_ALPH_STR) {
  293.             HTAAScheme scheme = HTAAScheme_enum(lex_buffer);
  294.             if (scheme != HTAA_UNKNOWN) {
  295.                 if (!prot->valid_schemes)
  296.                 prot->valid_schemes = HTList_new();
  297.                 HTList_addObject(prot->valid_schemes,(void*)scheme);
  298.                 if (TRACE) fprintf(stderr, "%s %s `%s'\n",
  299.                            "HTAA_parseProtFile: valid",
  300.                            "authentication scheme:",
  301.                            HTAAScheme_name(scheme));
  302.             }
  303.             else if (TRACE) fprintf(stderr, "%s %s `%s'\n",
  304.                         "HTAA_parseProtFile: unknown",
  305.                         "authentication scheme:",
  306.                         lex_buffer);
  307.             
  308.             if (LEX_ITEM_SEP != (lex_item = lex(fp)))
  309.                 break;
  310.             /*
  311.             ** Here lex_item == LEX_ITEM_SEP; after item separator
  312.             ** it is ok to have one or more newlines (LEX_REC_SEP)
  313.             ** and they are ignored (continuation line).
  314.             */
  315.             do {
  316.                 lex_item = lex(fp);
  317.             } while (lex_item == LEX_REC_SEP);
  318.             } /* while items in list */
  319.         } /* if "Authenticate" */
  320.  
  321.         else if (0==strncasecomp(fieldname, "mask", 4)) {
  322.             prot->mask_group = HTAA_parseGroupDef(fp);
  323.             lex_item=LEX_REC_SEP; /*groupdef parser read this already*/
  324.             if (TRACE) {
  325.             if (prot->mask_group) {
  326.                 fprintf(stderr,
  327.                     "HTAA_parseProtFile: Mask group:\n");
  328.                 HTAA_printGroupDef(prot->mask_group);
  329.             } else fprintf(stderr, "HTAA_parseProtFile: %s\n",
  330.                        "Mask group syntax error");
  331.             }
  332.         } /* if "Mask" */
  333.  
  334.         else {    /* Just a name-value pair, put it to assoclist */
  335.  
  336.             if (LEX_ALPH_STR == (lex_item = lex(fp))) {
  337.             if (!prot->values)
  338.                 prot->values = HTAssocList_new();
  339.             HTAssocList_add(prot->values, fieldname, lex_buffer);
  340.             lex_item = lex(fp);  /* Read record separator */
  341.             if (TRACE) fprintf(stderr, 
  342.                        "%s `%s' bound to value `%s'\n",
  343.                        "HTAA_parseProtFile: Name",
  344.                        fieldname, lex_buffer);
  345.             }
  346.         } /* else name-value pair */
  347.  
  348.         } /* if valid field */
  349.  
  350.         if (lex_item != LEX_EOF  &&  lex_item != LEX_REC_SEP) {
  351.         if (TRACE) fprintf(stderr, "%s %s %d (that line ignored)\n",
  352.                    "HTAA_parseProtFile: Syntax error",
  353.                    "in protection setup file at line",
  354.                    lex_line);
  355.         do {
  356.             lex_item = lex(fp);
  357.         } while (lex_item != LEX_EOF && lex_item != LEX_REC_SEP);
  358.         } /* if syntax error */
  359.     } /* while not end-of-file */
  360.     } /* if valid parameters */
  361. }
  362.  
  363.  
  364.  
  365.  
  366. /* PRIVATE                        HTAAProt_new()
  367. **        ALLOCATE A NEW HTAAProt STRUCTURE AND
  368. **        INITIALIZE IT FROM PROTECTION SETUP FILE
  369. ** ON ENTRY:
  370. **    cur_docname    current filename after rule translations.
  371. **    prot_filename    protection setup file name.
  372. **            If NULL, not an error.
  373. **    ids        Uid and gid names or numbers,
  374. **            examples:
  375. **                james    ( <=> james.nogroup)
  376. **                .www    ( <=> nobody.www)
  377. **                james.www
  378. **                james.69
  379. **                1422.69
  380. **                1422.www
  381. **
  382. **            May be NULL, defaults to nobody.nogroup.
  383. **            Should be NULL, if prot_file is NULL.
  384. **
  385. ** ON EXIT:
  386. **    returns        returns a new and initialized protection
  387. **            setup structure.
  388. **            If setup file is already read in (found
  389. **            in cache), only sets uid_name and gid
  390. **            fields, and returns that.
  391. */
  392. PRIVATE HTAAProt *HTAAProt_new ARGS3(CONST char *,    cur_docname,
  393.                      CONST char *,    prot_filename,
  394.                      CONST char *,    ids)
  395. {
  396.     HTList *cur = prot_cache;
  397.     HTAAProtCache *cache_item = NULL;
  398.     HTAAProt *prot;
  399.     FILE *fp;
  400.  
  401.     if (!prot_cache)
  402.     prot_cache = HTList_new();
  403.     
  404.     while (NULL != (cache_item = (HTAAProtCache*)HTList_nextObject(cur))) {
  405.     if (!strcmp(cache_item->prot_filename, prot_filename))
  406.         break;
  407.     }
  408.     if (cache_item) {
  409.     prot = cache_item->prot;
  410.     if (TRACE) fprintf(stderr, "%s `%s' already in cache\n",
  411.                "HTAAProt_new: Protection file", prot_filename);
  412.     } else {
  413.     if (TRACE) fprintf(stderr,
  414.                "HTAAProt_new: Loading protection file `%s'\n",
  415.                prot_filename);
  416.  
  417.     if (!(prot = (HTAAProt*)malloc(sizeof(HTAAProt))))
  418.         outofmem(__FILE__, "HTAAProt_new");
  419.  
  420.     prot->template    = NULL;
  421.     prot->filename    = NULL;
  422.     prot->uid_name    = NULL;
  423.     prot->gid_name    = NULL;
  424.     prot->valid_schemes = HTList_new();
  425.     prot->mask_group= NULL;        /* Masking disabled by defaults */
  426.     prot->values    = HTAssocList_new();
  427.  
  428.     if (prot_filename && NULL != (fp = fopen(prot_filename, "r"))) {
  429.         HTAA_parseProtFile(prot, fp);
  430.         fclose(fp);
  431.         if (!(cache_item = (HTAAProtCache*)malloc(sizeof(HTAAProtCache))))
  432.         outofmem(__FILE__, "HTAAProt_new");
  433.         cache_item->prot = prot;
  434.         cache_item->prot_filename = NULL;
  435.         StrAllocCopy(cache_item->prot_filename, prot_filename);
  436.         HTList_addObject(prot_cache, (void*)cache_item);
  437.     }
  438.     else if (TRACE) fprintf(stderr, "HTAAProt_new: %s `%s'\n",
  439.                 "Unable to open protection setup file",
  440.                 (prot_filename ? prot_filename : "(null)"));
  441.     }
  442.  
  443.     if (cur_docname)
  444.     StrAllocCopy(prot->filename, cur_docname);
  445.     HTAA_setIds(prot, ids);
  446.  
  447.     return prot;
  448. }
  449.  
  450.  
  451.  
  452. /* PUBLIC                    HTAA_setDefaultProtection()
  453. **        SET THE DEFAULT PROTECTION MODE
  454. **        (called by rule system when a
  455. **        "defprot" rule is matched)
  456. ** ON ENTRY:
  457. **    cur_docname    is the current result of rule translations.
  458. **    prot_filename    is the protection setup file (second argument
  459. **            for "defprot" rule, optional)
  460. **    ids        contains user and group names separated by
  461. **            a dot, corresponding to the uid
  462. **            gid under which the server should run,
  463. **            default is "nobody.nogroup" (third argument
  464. **            for "defprot" rule, optional; can be given
  465. **            only if protection setup file is also given).
  466. **
  467. ** ON EXIT:
  468. **    returns        nothing.
  469. **            Sets the module-wide variable default_prot.
  470. */
  471. PUBLIC void HTAA_setDefaultProtection ARGS3(CONST char *,    cur_docname,
  472.                         CONST char *,    prot_filename,
  473.                         CONST char *,    ids)
  474. {
  475.     default_prot = NULL;    /* Not free()'d because this is in cache */
  476.  
  477.     if (prot_filename) {
  478.     default_prot = HTAAProt_new(cur_docname, prot_filename, ids);
  479.     } else {
  480.     if (TRACE) fprintf(stderr, "%s %s\n",
  481.                "HTAA_setDefaultProtection: ERROR: Protection file",
  482.                "not specified (obligatory for DefProt rule)!!\n");
  483.     }
  484. }
  485.  
  486.  
  487.  
  488. /* PUBLIC                    HTAA_setCurrentProtection()
  489. **        SET THE CURRENT PROTECTION MODE
  490. **        (called by rule system when a
  491. **        "protect" rule is matched)
  492. ** ON ENTRY:
  493. **    cur_docname    is the current result of rule translations.
  494. **    prot_filename    is the protection setup file (second argument
  495. **            for "protect" rule, optional)
  496. **    ids        contains user and group names separated by
  497. **            a dot, corresponding to the uid
  498. **            gid under which the server should run,
  499. **            default is "nobody.nogroup" (third argument
  500. **            for "protect" rule, optional; can be given
  501. **            only if protection setup file is also given).
  502. **
  503. ** ON EXIT:
  504. **    returns        nothing.
  505. **            Sets the module-wide variable current_prot.
  506. */
  507. PUBLIC void HTAA_setCurrentProtection ARGS3(CONST char *,    cur_docname,
  508.                         CONST char *,    prot_filename,
  509.                         CONST char *,    ids)
  510. {
  511.     current_prot = NULL;    /* Not free()'d because this is in cache */
  512.  
  513.     if (prot_filename) {
  514.     current_prot = HTAAProt_new(cur_docname, prot_filename, ids);
  515.     } else {
  516.     if (default_prot) {
  517.         current_prot = default_prot;
  518.         HTAA_setIds(current_prot, ids);
  519.         if (TRACE) fprintf(stderr, "%s %s %s\n",
  520.                    "HTAA_setCurrentProtection: Protection file",
  521.                    "not specified for Protect rule",
  522.                    "-- using default protection");
  523.     } else {
  524.         if (TRACE) fprintf(stderr, "%s %s %s\n",
  525.                    "HTAA_setCurrentProtection: ERROR: Protection",
  526.                    "file not specified for Protect rule, and",
  527.                    "default protection is not set!!");
  528.     }
  529.     }
  530. }
  531.  
  532.  
  533.  
  534. /* PUBLIC                    HTAA_getCurrentProtection()
  535. **        GET CURRENT PROTECTION SETUP STRUCTURE
  536. **        (this is set up by callbacks made from
  537. **         the rule system when matching "protect"
  538. **         (and "defprot") rules)
  539. ** ON ENTRY:
  540. **    HTTranslate() must have been called before calling
  541. **    this function.
  542. **
  543. ** ON EXIT:
  544. **    returns    a HTAAProt structure representing the
  545. **        protection setup of the HTTranslate()'d file.
  546. **        This must not be free()'d.
  547. */
  548. PUBLIC HTAAProt *HTAA_getCurrentProtection NOARGS
  549. {
  550.     return current_prot;
  551. }
  552.  
  553.  
  554.  
  555. /* PUBLIC                    HTAA_getDefaultProtection()
  556. **        GET DEFAULT PROTECTION SETUP STRUCTURE
  557. **        AND SET IT TO CURRENT PROTECTION
  558. **        (this is set up by callbacks made from
  559. **         the rule system when matching "defprot"
  560. **         rules)
  561. ** ON ENTRY:
  562. **    HTTranslate() must have been called before calling
  563. **    this function.
  564. **
  565. ** ON EXIT:
  566. **    returns    a HTAAProt structure representing the
  567. **        default protection setup of the HTTranslate()'d
  568. **        file (if HTAA_getCurrentProtection() returned
  569. **        NULL, i.e. if there is no "protect" rule
  570. **        but ACL exists, and we need to know default
  571. **        protection settings).
  572. **        This must not be free()'d.
  573. ** IMPORTANT:
  574. **    As a side-effect this tells the protection system that
  575. **    the file is in fact protected and sets the current
  576. **    protection mode to default.
  577. */
  578. PUBLIC HTAAProt *HTAA_getDefaultProtection NOARGS
  579. {
  580.     if (!current_prot) {
  581.     current_prot = default_prot;
  582.     default_prot = NULL;
  583.     }    
  584.     return current_prot;
  585. }
  586.  
  587.  
  588.  
  589. /* SERVER INTERNAL                    HTAA_clearProtections()
  590. **        CLEAR DOCUMENT PROTECTION MODE
  591. **        (ALSO DEFAULT PROTECTION)
  592. **        (called by the rule system)
  593. ** ON ENTRY:
  594. **    No arguments.
  595. **
  596. ** ON EXIT:
  597. **    returns    nothing.
  598. **        Frees the memory used by protection information.
  599. */
  600. PUBLIC void HTAA_clearProtections NOARGS
  601. {
  602.     current_prot = NULL;    /* These are not freed because    */
  603.     default_prot = NULL;    /* they are actually in cache.    */
  604. }
  605.  
  606.  
  607.